/*This file is part of StarNoid.

StarNoid is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

StarNoid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with StarNoid.  If not, see <http://www.gnu.org/licenses/>.*/

#include <boost/lexical_cast.hpp>
#include <iostream>
#include <ctime>
#include "../include/ventana.h"

//Constructor
Ventana::Ventana():Gosu::Window(1024, 768, true){
	//Cadena que contendrá el directorio del juego
	wstring directorio=Gosu::sharedResourcePrefix();
	//Inicializamos todos los punteros de las imágenes del juego y de la fuente
	fondo = new Gosu::Image(graphics(),directorio + L"imagenes/fondo.png");
	bola = new Gosu::Image(graphics(),directorio + L"imagenes/bola.png");
	sable = new Gosu::Image(graphics(),directorio + L"imagenes/sable.png");
	clon = new Gosu::Image(graphics(),directorio + L"imagenes/clon.png");
	fuente = new Gosu::Font(graphics(),directorio + L"fuente/anewhope.ttf",35,0);
	
	//Inicializamos el estado actual al estado inicial de reposo es decir START
	EstadoActual=START;
	
	//Propiedades del sable
	Sable.ancho = sable->width();
	Sable.alto = sable->height();
	Sable.izquierda = (LIMITE_IZQUIERDA + LIMITE_DERECHA)/2 - Sable.ancho/2;
	Sable.arriba = 718;
	
	//Propiedades de la bola
	Bola.ancho = bola->width();
	Bola.alto = bola->height();
	
	//Inicializamos las velocidades
	v_vertical = 0;
	v_horizontal = 0;
	
	//Llamamos al método RellenaConClones() para llenar de clones el escenario
	RellenaConClones();
	
	//Inicializamos los puntos y las vidas
	puntos = 0;
	vidas = 3;
}

//Destructor, aquí se destruyen todos los punteros antes creados
Ventana::~Ventana(){
	delete fondo;
	delete bola;
	delete sable;
	delete clon;
	delete fuente;
}

//Método donde se va actualizando el escenario
void Ventana::update(){
	//Cuando hemos destruido todos los bloques reiniciamos el escenario, y aumentamos el contador de las vidas
	if(n_bloques == 0){
		RellenaConClones();
		EstadoActual = START;
		if(vidas < 10)
			++vidas;
	}
	//Si pierdes todas las vidas, se reinicia el escenario, y se pierden los puntos
	if(vidas == 0){
		RellenaConClones();
		EstadoActual = START;
		vidas = 3;
		puntos = 0;
	}
	
	//Movemos el sable a donde vaya el raton
	double posicionSable=input().mouseX() - Sable.ancho/2;
	if(posicionSable >= LIMITE_IZQUIERDA and posicionSable <= LIMITE_SABLE){
		Sable.izquierda = posicionSable;
	}
	else{
		if(posicionSable < LIMITE_IZQUIERDA){
			Sable.izquierda = LIMITE_IZQUIERDA;
		}
		else{
			Sable.izquierda = LIMITE_SABLE;
		}
	}
	
	//Ponemos la bola pegada al centro del sable
	if(EstadoActual == START){
		Bola.izquierda = Sable.izquierda + Sable.ancho/2 - Bola.ancho/2;
		Bola.arriba = Sable.arriba - Bola.alto;
	}
	//Analizamos las posibles colisiones y le damos la nueva trayectoria a la bola
	else if(EstadoActual == MOVIMIENTO){
			Bola.izquierda += v_horizontal;
			Bola.arriba += v_vertical;
			if(Bola.izquierda < LIMITE_IZQUIERDA){
				v_horizontal = -v_horizontal;
				Bola.izquierda = LIMITE_IZQUIERDA;
			}
			else if(Bola.izquierda + Bola.ancho > LIMITE_DERECHA){
					v_horizontal = -v_horizontal;
					Bola.izquierda = LIMITE_DERECHA - Bola.ancho;
				}
				else if(Bola.arriba < LIMITE_ARRIBA){
						v_vertical = -v_vertical;
						Bola.arriba = LIMITE_ARRIBA;
					}
					else if(Bola.arriba > LIMITE_ABAJO){
							EstadoActual = START;
							--vidas;
						}
		}
	
	//Colisión de la bola con el sable
	if(Bola.arriba < Sable.arriba and Sable.colisiona(Bola) and v_vertical > 0){
		v_vertical = -v_vertical;
		float distanciacentro = (Bola.izquierda + Bola.ancho/2) - (Sable.izquierda + Sable.ancho/2);
		//Descomponemos la velocidad en velocidad horizontal y vertical mediante los métodos offsetX() y offsetY()
		v_horizontal = Gosu::offsetX(distanciacentro/((float)Sable.ancho/2)*ANGULO,VELOCIDAD);
		v_vertical = Gosu::offsetY(distanciacentro/((float)Sable.ancho/2)*ANGULO,VELOCIDAD);
	}
	
	//Colisiones con los bloques
	bool colision = false;
	//Recorremos todos los bloques, si este no está destruido y ha habido una colisión, restamos el contador de bloques
	//ponemos a false el estado del bloque destruido y cambiamos la trayectoria de la bola dependiendo si la colisión ha sido
	//horizontal o vertical
	for(size_t i=0; i!=7 and !colision; ++i)
		for(size_t j=0; j!=12 and !colision; ++j){
			if(!clones[i][j].EstadoBloque)
				continue;
			if(clones[i][j].QueLado(Bola) == 0)
				continue;
			else{
				colision = true;
				--n_bloques;
				puntos+=100;
				clones[i][j].EstadoBloque=false;
				if(clones[i][j].QueLado(Bola) == 1)
					v_vertical = -v_vertical;
				else
					v_horizontal = -v_horizontal;
			}
		}
}

//Métodos para dibujar los elementos del juego
void Ventana::draw(){
	fondo->draw(0,0,0);
	sable->draw(Sable.izquierda, Sable.arriba, 1);
	bola->draw(Bola.izquierda,Bola.arriba,1);
	//Dibujamos los clones que no estén destruidos
	for(size_t i=0;i!=7;++i)
		for(size_t j=0;j!=12;++j){
			if(!clones[i][j].EstadoBloque)continue;
				clon->draw(clones[i][j].izquierda,clones[i][j].arriba , 1, 1, 1);
		}
	fuente->draw(boost::lexical_cast<wstring>(puntos),800,200,1);
	fuente->draw(boost::lexical_cast<wstring>(vidas),800,250,1);
}

//Analizamos que botones se han pulsado
void Ventana::buttonDown(Gosu::Button b){
	if(b==Gosu::kbEscape)
		close();
	else if(EstadoActual == START and b == Gosu::msLeft){
			EstadoActual=MOVIMIENTO;
			v_vertical = -VELOCIDAD;
			v_horizontal=0;
		}
}

//Método para llenar el escenario de clones
void Ventana::RellenaConClones(){
	//Mediante un bucle recorremos la matriz de los clones y les vamos asignando
	//sus posiciones y ponemos su estado a true para que este sea visible
	for(size_t i=0;i!=7;++i)
		for(size_t j=0;j!=12;++j){
			clones[i][j].izquierda=PRIMER_BLOQUE_X + TAM_BLOQUE * j;
			clones[i][j].arriba=PRIMER_BLOQUE_Y + TAM_BLOQUE * i;
			clones[i][j].EstadoBloque=true;
		}
	n_bloques=84;
}

